home *** CD-ROM | disk | FTP | other *** search
/ Video Toaster 4.2 / Video Toaster v4.2.iso / programs / documentation / lightwave / sdk / sample / layerset / layerset.c next >
Encoding:
C/C++ Source or Header  |  1995-03-13  |  5.7 KB  |  266 lines

  1. /*
  2.  * LAYERSET.C -- Modeler Plugin Command
  3.  *         Two operations to change layers
  4.  *
  5.  * written by Stuart Ferguson
  6.  * last revision  12/6/94
  7.  */
  8. #include <splug.h>
  9. #include <lwmod.h>
  10. #include <stdio.h>
  11.  
  12.  
  13. /*
  14.  * If the DEBUG symbol is defined, a debugging output window will be
  15.  * opened as the server data for this module.  Unfortunately this only
  16.  * works on the Amiga where we can open console windows as simple files.
  17.  */
  18. /* #define DEBUG */
  19.  
  20. #ifndef _AMIGA
  21.  #ifdef  DEBUG
  22.   #undef DEBUG
  23.  #endif
  24. #endif
  25.  
  26. #ifdef DEBUG
  27.  #define DPRT(a)    fprintf a
  28.  #define DFLUSH        fflush (debugPort)
  29. #else
  30.  #define DPRT(a)
  31.  #define DFLUSH
  32. #endif
  33.  
  34.  
  35. /*
  36.  * Send a command to select the next empty layer after this one.
  37.  */
  38.     XCALL_(static int)
  39. NextEmpty (
  40.     long             version,
  41.     GlobalFunc        *global,
  42.     ModCommand        *local,
  43.     FILE            *debugPort)
  44. {
  45.     StateQueryFuncs        *query;
  46.     unsigned int         empty, fg;
  47.     CommandCode         ccSetLayer;
  48.     DynaValue         dval;
  49.     int             num, i, max, l, lset;
  50.  
  51.     /*
  52.      * Standard version check.
  53.      */
  54.     XCALL_INIT;
  55.     if (version != 1)
  56.         return AFUNC_BADVERSION;
  57.  
  58.     /*
  59.      * Get the state query functions and the command code for the
  60.      * set layer command.
  61.      */
  62.     query = (*global) ("LWM: State Query", GFUSE_TRANSIENT);
  63.     if (!query)
  64.         return AFUNC_BADGLOBAL;
  65.  
  66.     ccSetLayer = (*local->lookup) (local->data, "setlayer");
  67.     if (!ccSetLayer)
  68.         return AFUNC_BADLOCAL;
  69.  
  70.     DPRT ((debugPort, "Next Empty...\n"));
  71.  
  72.     /*
  73.      * Get the total number of layers and the mask for the empty layers
  74.      * and current layers.  Then scan through the fg layer mask and find
  75.      * the maximum layer number that is selected.
  76.      */
  77.     num   = (*query->numLayers) ();
  78.     fg    = (*query->layerMask) (OPLYR_FG);
  79.     empty = (*query->layerMask) (OPLYR_EMPTY);
  80.  
  81.     DPRT ((debugPort, "num %d, fg %d, empty %d\n", num, fg, empty));
  82.  
  83.     max = -1;
  84.     for (i = 0; i < num; i++)
  85.         if ((fg & (1 << i)) && i > max)
  86.             max = i;
  87.  
  88.     DPRT ((debugPort, "max current layer %d\n", max));
  89.  
  90.     /*
  91.      * Starting from the last layer selected and scanning through the
  92.      * rest of the layers (wrapping around to the start layers), stop
  93.      * on the first empty layer that is not selected.
  94.      */
  95.     lset = 0;
  96.     for (i = 0; i < num - 1; i++) {
  97.         l = 1 << ((max + i + 1) % num);
  98.         if ((fg & l) == 0 && (empty & l)) {
  99.             lset = l;
  100.             break;
  101.         }
  102.     }
  103.  
  104.     /*
  105.      * Send the "setlayer" command with the chosen layer as argument.
  106.      * The selected data for the command is irrelevant since nothing
  107.      * will change except display state.
  108.      */
  109.     if (lset) {
  110.         DPRT ((debugPort, "Next empty layer set (mask=%d).\n", lset));
  111.         dval.type = DY_LAYERS;
  112.         dval.intv.value = lset;
  113.         (*local->execute) (local->data, ccSetLayer, 1,
  114.                    &dval, OPSEL_GLOBAL, NULL);
  115.     } else
  116.         DPRT ((debugPort, "No next empty layer found.\n"));
  117.  
  118.     DFLUSH;
  119.     return AFUNC_OK;
  120. }
  121.  
  122.  
  123. /*
  124.  * Attempt to add layer number k to the BG layer mask.  Ignore this layer
  125.  * if it is out of range, if it is not empty, if it is currently displayed
  126.  * or if it is already in the BG mask.  If the layer can be added, also
  127.  * attempt to add the adjacent layers recursively.
  128.  */
  129.     static unsigned int
  130. AddBGLayer (
  131.     unsigned int         bg,
  132.     unsigned int         fg,
  133.     unsigned int         empty,
  134.     int             num,
  135.     int             k)
  136. {
  137.     unsigned int         l;
  138.  
  139.     if (k < 0 || k >= num)
  140.         return bg;
  141.  
  142.     l = 1 << k;
  143.     if ((l & empty) || (l & fg) || (l & bg))
  144.         return bg;
  145.  
  146.     bg = bg | l;
  147.     bg = AddBGLayer (bg, fg, empty, num, k - 1);
  148.     return AddBGLayer (bg, fg, empty, num, k + 1);
  149. }
  150.  
  151.  
  152. /*
  153.  * Select all background layers near currently selected ones.
  154.  */
  155.     XCALL_(static int)
  156. AllBG (
  157.     long             version,
  158.     GlobalFunc        *global,
  159.     ModCommand        *local,
  160.     FILE            *debugPort)
  161. {
  162.     StateQueryFuncs        *query;
  163.     unsigned int         empty, fg, bg;
  164.     CommandCode         ccSetBLayer;
  165.     DynaValue         dval;
  166.     int             num, i;
  167.  
  168.     /*
  169.      * Standard version check.
  170.      */
  171.     XCALL_INIT;
  172.     if (version != 1)
  173.         return AFUNC_BADVERSION;
  174.  
  175.     /*
  176.      * Get the state query functions and the command code for the
  177.      * set bg layer command.
  178.      */
  179.     query = (*global) ("LWM: State Query", GFUSE_TRANSIENT);
  180.     if (!query)
  181.         return AFUNC_BADGLOBAL;
  182.  
  183.     ccSetBLayer = (*local->lookup) (local->data, "setblayer");
  184.     if (!ccSetBLayer)
  185.         return AFUNC_BADLOCAL;
  186.  
  187.     DPRT ((debugPort, "All BG Layers...\n"));
  188.  
  189.     /*
  190.      * Get the total number of layers and the mask for the empty layers
  191.      * and current layers.
  192.      */
  193.     num   = (*query->numLayers) ();
  194.     fg    = (*query->layerMask) (OPLYR_FG);
  195.     empty = (*query->layerMask) (OPLYR_EMPTY);
  196.  
  197.     DPRT ((debugPort, "num %d, fg %d, empty %d\n", num, fg, empty));
  198.  
  199.     /*
  200.      * Recursively add all layers adjacent to fg layers to the background
  201.      * set.  Non-empty layers will be ignored.
  202.      */
  203.     bg = 0;
  204.     for (i = 0; i < num; i++) {
  205.         if ((fg & (1 << i)) == 0)
  206.             continue;
  207.  
  208.         bg = AddBGLayer (bg, fg, empty, num, i - 1);
  209.         bg = AddBGLayer (bg, fg, empty, num, i + 1);
  210.     }
  211.  
  212.     /*
  213.      * If we get a valid set of BG layers, set the background.
  214.      */
  215.     if (bg) {
  216.         DPRT ((debugPort, "setting new background %d\n", bg));
  217.  
  218.         dval.type = DY_LAYERS;
  219.         dval.intv.value = bg;
  220.         (*local->execute) (local->data, ccSetBLayer, 1,
  221.                    &dval, OPSEL_GLOBAL, NULL);
  222.     }
  223.  
  224.     DFLUSH;
  225.     return AFUNC_OK;
  226. }
  227.  
  228.  
  229. /*
  230.  * Startup and shutdown are called to load and unload this plugin module.
  231.  * The return value from Startup is passed to the activation functions as
  232.  * serverData, and must be non-null if the load was successful.  Since
  233.  * we're only opening the debug window, these functions are optional.
  234.  */
  235. #ifdef DEBUG
  236.     void *
  237. Startup (void)
  238. {
  239.     FILE            *debugPort;
  240.  
  241.     debugPort = fopen ("con:10/10/300/180/XYZDebug", "w+");
  242.     if (debugPort)
  243.         fprintf (debugPort, "Layer-Set Server\n");
  244.  
  245.     return debugPort;
  246. }
  247.  
  248.     void
  249. Shutdown (
  250.     FILE            *debugPort)
  251. {
  252.     fclose (debugPort);
  253. }
  254. #endif
  255.  
  256.  
  257. /*
  258.  * ServerDesc records for each entry point in this multi-server module.
  259.  */
  260. const char        class[] = "CommandSequence";
  261. ServerRecord        ServerDesc[] = {
  262.     { class, "Demo_NextEmptyLayer",        NextEmpty },
  263.     { class, "Demo_AllBGLayers",        AllBG },
  264.     { NULL }
  265. };
  266.